package com.liuyucheng.util.m4s;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class FileProcessor {

    private static final String homeDir = "E:\\B站目录\\下载目录";
    private static final String destDir = "D:\\迅雷下载\\原文件";
    private static final String outputDir = "D:\\迅雷下载\\解密后文件";

    public static void main(String[] args) throws Exception {
        //指定一个目录，就是b站缓存视频的目录，然后遍历所有的m4s文件 解密后统一输出到一个目录
        File homeDirectory = new File(homeDir);
        File[] listFiles = homeDirectory.listFiles();
        for (File item : listFiles) {
            if(!item.isDirectory()){
                continue;
            }
            List<File> fileList = Arrays.stream(item.listFiles()).filter(element -> {
                return element.getName().endsWith("m4s");
            }).collect(Collectors.toList());
            //每个子文件夹下的m4s文件
            if(fileList.size()!=2){
                throw new Exception("m4s文件数量不对，是否是下载有问题");
            }
            File file1 = fileList.get(0);
            File file2 = fileList.get(1);
            //获取到网页原标题
            String title = getOriginalTitle(file1);
            if(file1.length()>file2.length()){ // 那就认为是视频文件
                removeFirstNineBytesAndSave(title, file1,"mp4");
                removeFirstNineBytesAndSave(title, file2,"aac");
            }else{
                removeFirstNineBytesAndSave(title, file1,"aac");
                removeFirstNineBytesAndSave(title, file2,"mp4");
            }
        }

        //开始解密，解密后合并音视频，然后输出到一个统一的文件夹里面
        File directory = new File(destDir);
        File[] files = directory.listFiles();
        List<File> fileList = Arrays.stream(files).filter(element -> {
            return element.getName().endsWith("mp4");
        }).collect(Collectors.toList());
        for (File file : fileList) {
            String videoPath = file.getAbsolutePath();
            String audioPath = file.getAbsolutePath().replace("mp4","aac");
            String outputPath = outputDir + File.separator + file.getName();
            VideoAudioMerger.mergeVideoAndAudio(videoPath, audioPath, outputPath);
            //合并成功后删除原文件
            if(new File(videoPath).delete()){
                log.info("文件删除成功:{}",videoPath);
            }
            if(new File(audioPath).delete()){
                log.info("文件删除成功:{}",audioPath);
            }
        }
    }

    private static String getOriginalTitle(File file) throws Exception {
        List<File> list = Arrays.stream(file.getParentFile().listFiles()).filter(item -> {
            return item.getName().contains("videoInfo.json");
        }).collect(Collectors.toList());
        if(list.size()==0){
            throw new Exception("解析视频信息出错");
        }
        File videoInfoFile = list.get(0);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(videoInfoFile), StandardCharsets.UTF_8));
        String line = bufferedReader.readLine();
        JSONObject object = JSON.parseObject(line);
        String title = object.get("title").toString();
        System.out.println("文件标题 = " + title);
        return title;
    }

    /**
     * 解密b站缓存的视频和音频文件
     * @param title 文件标题
     * @param file 文件
     * @throws IOException 异常
     */
    public static void removeFirstNineBytesAndSave(String title, File file,String postfix) throws IOException {
        // 创建输入流来读取文件
        FileInputStream fis = null;
        // 创建输出流来写入新文件
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(file);
            //D:\Captures\bilibili\1626753308\1626753308-1-30112.m4s
            //原文件名称
//            String name = file.getName();
//            String firstName = name.split("-")[0];
            String outputFilePath = destDir + File.separator + title + "." + postfix;
            System.out.println("正在导出文件: " + outputFilePath);
            fos = new FileOutputStream(outputFilePath);
            // 跳过前9个字节
            fis.skip(9);
            // 创建一个缓冲区来读取和写入数据
            byte[] buffer = new byte[1024];
            int bytesRead;

            // 读取文件内容，除了前9个字节，并写入新文件
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }

            // 刷新输出流，确保所有数据都被写入
            fos.flush();

        } finally {
            // 关闭流，以释放系统资源
            if (fis != null) {
                fis.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
    }

}